package com.qq.weixin.wrapper;

import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;

import com.qq.weixin.encrypt.aes.AesException;
import com.qq.weixin.encrypt.aes.WXBizMsgCrypt;
import com.qq.weixin.model.OpenInfo;

public class OpenMsgWrapper {

  Logger logger = Logger.getLogger(getClass());

  private OpenInfo openInfo;
  private Map<String, Object> paramMap;
  private WXBizMsgCrypt crypt;

  public OpenMsgWrapper(OpenInfo openInfo, Map<String, Object> paramMap) {
    this.openInfo = openInfo;
    this.paramMap = paramMap;

  }

  public OpenInfo getOpenInfo() {
    return openInfo;
  }

  public Map<String, Object> getParamMap() {
    return paramMap;
  }

  private void initCrypt() throws AesException {
    if (crypt == null) {
      crypt = new WXBizMsgCrypt(this.openInfo.getToken(), this.openInfo.getEncodingAESKey(), openInfo.getAppId());
    }
  }

  public boolean verifyRequest() {

    String token = this.openInfo.getToken();
    String timestamp = paramMap.get("timestamp") != null ? String.valueOf(paramMap.get("timestamp")) : null;
    String nonce = paramMap.get("nonce") != null ? String.valueOf(paramMap.get("nonce")) : null;
    String signature = paramMap.get("signature") != null ? String.valueOf(paramMap.get("signature")) : null;

    if (timestamp == null || nonce == null) {
      return false;
    }

    String $signature = DigestUtils.shaHex(token + timestamp + nonce);

    if ($signature.equals(signature)) {
      return true;
    }

    logger.warn("vs failed:" + "token=" + token + ",timestamp=" + timestamp + ",nonce=" + nonce + ",signature=" + signature
        + ",$signature=" + $signature);
    return false;
  }

  public String unwrap(String data) throws AesException {
    if (this.openInfo.isUseAESKey()) {
      initCrypt();
      String msg_signature = paramMap.get("msg_signature") != null ? String.valueOf(paramMap.get("msg_signature")) : null;
      String timestamp = paramMap.get("timestamp") != null ? String.valueOf(paramMap.get("timestamp")) : null;
      String nonce = paramMap.get("nonce") != null ? String.valueOf(paramMap.get("nonce")) : null;
      return crypt.decryptMsg(msg_signature, timestamp, nonce, data);
    } else {
      return data;
    }
  }

  public String wrap(String data) throws AesException {
    if (this.openInfo.isUseAESKey()) {
      initCrypt();
      String timestamp = paramMap.get("timestamp") != null ? String.valueOf(paramMap.get("timestamp")) : null;
      String nonce = paramMap.get("nonce") != null ? String.valueOf(paramMap.get("nonce")) : null;
      return crypt.encryptMsg(data, timestamp, nonce);
    } else {
      return data;
    }
  }

}
